package com.qqt.csr.order.controller;

import com.qqt.csr.common.exception.StatusCode;
import com.qqt.csr.common.idempotent.Idempotent;
import com.qqt.csr.common.interceptor.auth.Authorize;
import com.qqt.csr.common.log.Log;
import com.qqt.csr.common.operalog.BusinessType;
import com.qqt.csr.common.operalog.LogLevel;
import com.qqt.csr.common.operalog.OperationLog;
import com.qqt.csr.common.session.SessionContextHolder;
import com.qqt.csr.common.utils.ServiceAssert;
import com.qqt.csr.common.vo.resp.ObjectResponse;
import com.qqt.csr.order.assembler.WorkOrderAssembler;
import com.qqt.csr.order.entity.WorkOrder;
import com.qqt.csr.order.enums.WorkOrderEventEnum;
import com.qqt.csr.order.enums.WorkOrderStatusEnum;
import com.qqt.csr.order.service.ProcessingWorkOrderEventService;
import com.qqt.csr.order.service.statemachine.context.WorkOrderContext;
import com.qqt.csr.order.vo.req.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Authorize
@RestController
@RequestMapping("order/work")
@Tag(name = "工单处理", description = "工单处理")
public class WorkOrderCommandController {
    @Autowired
    private ProcessingWorkOrderEventService processingWorkOrderEventService;

    @PostMapping("/create")
    @Operation(summary = "创建工单")
    @Log(desc = "创建工单")
    @Idempotent(model = "work-order:create:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "新增工单", businessType = BusinessType.INSERT)
    public ObjectResponse<String> createWorkOrder(@Validated @RequestBody AddingWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = WorkOrderAssembler.INSTANCE.toWorkOrder(req);

        WorkOrderContext context = null;
        if (workOrder.isAllocated()) {
            context = processingWorkOrderEventService.processEvent(WorkOrderEventEnum.CREATED_ALLOCATED, workOrder);
        } else {
            context = processingWorkOrderEventService.processEvent(WorkOrderEventEnum.CREATED, workOrder);
        }
        return ObjectResponse.success(context.getToOrder().getId().toString());
    }

    @PostMapping("/edit")
    @Operation(summary = "编辑工单")
    @Log(desc = "编辑工单")
    @Idempotent(model = "work-order:edit:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "编辑工单", businessType = BusinessType.UPDATE)
    public ObjectResponse<String> editWorkOrder(@Validated @RequestBody EditingWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = WorkOrderAssembler.INSTANCE.toWorkOrder(req);

        if (WorkOrderStatusEnum.TO_CLAIM.getStatus().equals(workOrder.getStatus()) && workOrder.isAllocated()) {
            processingWorkOrderEventService.processEvent(WorkOrderEventEnum.EDIT_ALLOCATED, workOrder);
        } else {
            processingWorkOrderEventService.processEvent(WorkOrderEventEnum.EDITED, workOrder);
        }
        return ObjectResponse.success();
    }

    @PostMapping("/receive")
    @Operation(summary = "工单认领")
    @Log(desc = "工单认领")
    @Idempotent(model = "work-order:receive:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "工单认领", businessType = BusinessType.UPDATE)
    public ObjectResponse<String> receiveWorkOrder(@Validated @RequestBody ReceivingWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(req.getOrderId());
        workOrder.setDesigneeId(SessionContextHolder.getHeaderInfo().getUserId());

        processingWorkOrderEventService.processEvent(WorkOrderEventEnum.RECEIVED, workOrder);
        return ObjectResponse.success();
    }

    @PostMapping("/updateDesignee")
    @Operation(summary = "变更处理人")
    @Log(desc = "变更处理人")
    @Idempotent(model = "work-order:updateDesignee:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "变更处理人", businessType = BusinessType.UPDATE)
    public ObjectResponse<String> updateWorkOrderDesignee(@Validated @RequestBody UpdatedDesigneeWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(req.getOrderId());
        workOrder.setDesigneeId(req.getUserId());
        workOrder.setAllocateCause(StringUtils.isNotBlank(req.getAllocateCause()) ? req.getAllocateCause() : StringUtils.EMPTY);

        if (WorkOrderStatusEnum.TO_CLAIM.getStatus().equals(req.getStatus())) {
            processingWorkOrderEventService.processEvent(WorkOrderEventEnum.ALLOCATED, workOrder);
        } else {
            processingWorkOrderEventService.processEvent(WorkOrderEventEnum.UPDATED_DESIGNEE, workOrder);
        }
        return ObjectResponse.success();
    }

    @PostMapping("/delete")
    @Operation(summary = "删除工单")
    @Log(desc = "删除工单")
    @Idempotent(model = "work-order:delete:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "删除工单", businessType = BusinessType.DELETE)
    public ObjectResponse<String> deleteWorkOrder(@Validated @RequestBody DeletingWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(req.getOrderId());

        processingWorkOrderEventService.processEvent(WorkOrderEventEnum.DELETED, workOrder);
        return ObjectResponse.success();
    }

    @PostMapping("/suspend")
    @Operation(summary = "挂起工单")
    @Log(desc = "挂起工单")
    @Idempotent(model = "work-order:suspend:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "挂起工单", businessType = BusinessType.UPDATE)
    public ObjectResponse<String> suspendWorkOrder(@Validated @RequestBody SuspendingWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(req.getOrderId());

        processingWorkOrderEventService.processEvent(WorkOrderEventEnum.SUSPENDED, workOrder);
        return ObjectResponse.success();
    }

    @PostMapping("/recover")
    @Operation(summary = "取消挂起")
    @Log(desc = "取消挂起")
    @Idempotent(model = "work-order:recover:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "取消挂起", businessType = BusinessType.UPDATE)
    public ObjectResponse<String> recoverWorkOrder(@Validated @RequestBody RecoveringWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(req.getOrderId());

        processingWorkOrderEventService.processEvent(WorkOrderEventEnum.RECOVERED, workOrder);
        return ObjectResponse.success();
    }

    @PostMapping("/complete")
    @Operation(summary = "完成工单")
    @Log(desc = "完成工单")
    @Idempotent(model = "work-order:complete:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "完成工单", businessType = BusinessType.UPDATE)
    public ObjectResponse<String> completeWorkOrder(@Validated @RequestBody CompletingWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(req.getOrderId());

        processingWorkOrderEventService.processEvent(WorkOrderEventEnum.COMPLETED, workOrder);
        return ObjectResponse.success();
    }

    @PostMapping("/reopen")
    @Operation(summary = "重新打开工单")
    @Log(desc = "重新打开工单")
    @Idempotent(model = "work-order:reopen:")
    @OperationLog(level = LogLevel.HIGH, operationMenu = "工单管理", buttonName = "重新打开", businessType = BusinessType.UPDATE)
    public ObjectResponse<String> reopenWorkOrder(@Validated @RequestBody ReopeningWorkOrderReqVO req) {
        ServiceAssert.notNull(req, StatusCode.Common.NULL_ERROR.getCode(), "请求参数不能为空");

        WorkOrder workOrder = new WorkOrder();
        workOrder.setId(req.getOrderId());

        processingWorkOrderEventService.processEvent(WorkOrderEventEnum.REOPENED, workOrder);
        return ObjectResponse.success();
    }
}
